package com.lucenten.collect.gnss.handler.tools;

import cn.quevo.common.file.FileUtils;
import cn.quevo.common.lang.NumberUtils;
import cn.quevo.common.lang.StringUtils;
import com.lucenten.collect.Context;
import com.lucenten.collect.gnss.entity.GnssFile;
import com.lucenten.collect.gnss.entity.TecpTecl;
import com.lucenten.collect.gnss.entity.trans.TecpTeclTrans;
import com.lucenten.collect.gnss.enums.PathFileType;
import com.lucenten.collect.gnss.handler.files.PathFiles;
import com.lucenten.collect.gnss.service.SatelliteStationService;
import com.lucenten.mq.SendJmsInfo;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.*;
import java.util.*;

@Slf4j
public class TecpTeclTool {

    private SatelliteStationService satelliteStationService;

    public TecpTeclTool(SatelliteStationService satelliteStationService) {
        this.satelliteStationService = satelliteStationService;
    }
    public void merge(GnssFile gnssFile, Path oFile, String tecPath) {
        String ofileName = oFile.getFileName().normalize().toString();
        // 站点名称
        String stationName = ofileName.substring(0, 4);
        // 如果是错误站点，或者站点不在数据库，则忽略
        if (Context.ERROR_STATION.contains(stationName)) {
            return;
        }
        try {
            String suffix = ofileName.substring(0, 4) + gnssFile.getYear()+ ofileName.substring(4, ofileName.length() - 4) + ".dat";
            FileUtils.createAndNotExists(Paths.get(tecPath));
            String dataPath = oFile.getParent().normalize().toString();
            dataPath = dataPath.substring(0,dataPath.length() -1);
            Map<String,List<TecpTecl>> tecMap = this.getTecpTecl(gnssFile,oFile, dataPath,ofileName.substring(0,ofileName.length() -1));
            if (StringUtils.isEmpty(tecMap)) {
                log.info("TECL TECP IS NULL ");
                return;
            }
            Path gnss = Paths.get(tecPath,"TECPTECL_GNS_"+suffix);
            if (Files.exists(gnss)) {
                Files.delete(gnss);
            }
            boolean isFirst = true;
            for (Map.Entry<String,List<TecpTecl>> entry : tecMap.entrySet()) {
                this.write(tecPath,suffix, entry.getKey(), entry.getValue());
                this.write(gnss,entry.getValue(),isFirst);
                isFirst = false;
            }
//            SendJmsInfo.sendGnssMq(13, oFile.getFileName().normalize().toString(), 0);
        } catch (IOException e) {
            SendJmsInfo.sendGnssMq(13, oFile.getFileName().normalize().toString(), 1);
            log.error("O文件解析失败",e);
        }
    }
    private void write(Path file, List<TecpTecl> list, boolean isFirst) {
        List<String> lines = new ArrayList<>(list.size());
        for (TecpTecl tecpTecl : list) {
            lines.add(tecpTecl.join());
        }
        try {
            if (isFirst) {
                Files.write(file,lines);
                return;
            }
            Files.write(file,lines,StandardOpenOption.APPEND);
        } catch (IOException e) {
            log.error("TECPTECL_GNS_文件写入失败,",e);
        }

    }

    private void write(String savePath, String suffix,String type,List<TecpTecl> list) {
        Path path = Paths.get(savePath,this.getSaveFileName(suffix, type));
        List<String> lines = new ArrayList<>(list.size());
        for (TecpTecl tecpTecl : list) {
            lines.add(tecpTecl.join());
        }
        try {
            Files.write(path, lines);
        } catch (IOException e) {
            log.error(type+"文件写入失败,",e);
        }
    }

    private String getSaveFileName(String suffix,String type) {
        if (type.equalsIgnoreCase("N")) {
            return "TECPTECL_GPS_"+suffix;
        }
        if (type.equalsIgnoreCase("G")) {
            return "TECPTECL_GLO_"+suffix;
        }
        return "TECPTECL_BDS_"+suffix;
    }

    /**
     * 判定版本类型
     *
     * @param line
     * @param version
     * @return
     */
    private boolean isVersion(String line, String version) {
        return line.contains(version);
    }

    /**
     * 获取数据文件路径
     *
     * @param pathFileType
     * @return
     */
    private Path getDataPath(PathFileType pathFileType,String parentPath,String fName) {
        return Paths.get(parentPath.concat(pathFileType.name().toLowerCase()),fName.concat(pathFileType.name().toLowerCase()));
    }
    public Map<String,List<TecpTecl>> getTecpTecl(GnssFile gnssFile, Path oFile, String parentPath,String fName) throws IOException {

        // 获取O文件所有行记录
        List<String> oLines = Files.readAllLines(oFile);
        TecpTeclTrans tecpTeclTrans = new TecpTeclTrans();
        tecpTeclTrans.setStation(gnssFile.getStation());
        if (tecpTeclTrans.getStation() == null || StringUtils.isEmpty(oLines)) {
            log.error("站点信息不存在");
            return null;
        }
        boolean isVerTow =  this.isVersion(oLines.get(0), "2.");
        // 解析头部信息
        int index = OFileTools.analysisHeader(tecpTeclTrans, oLines, 1,isVerTow,gnssFile,satelliteStationService);
//        int weekSeconds = TecDateFormat.getWeekSeconds(gnssFile.getDateStr());
        tecpTeclTrans.setNavPath(new PathFiles().readPathData(getDataPath(PathFileType.N, parentPath, fName),isVerTow,PathFileType.N, gnssFile));
        tecpTeclTrans.setGavPath(new PathFiles().readPathData(getDataPath(PathFileType.G, parentPath, fName),isVerTow, PathFileType.G, gnssFile));
        tecpTeclTrans.setCavPath(new PathFiles().readPathData(getDataPath(PathFileType.C, parentPath, fName),isVerTow, PathFileType.C, gnssFile));


        // 卫星名称
        String startName = "";
        boolean versionTow = oLines.get(0).contains("2.");
        if (versionTow) {
            return this.getVersion2(oLines, index, tecpTeclTrans, gnssFile.getYear().toString());
        }

        return this.getVersion3(oLines,index, tecpTeclTrans, gnssFile.getYear().toString());
    }

    private Map<String,List<TecpTecl>> getVersion3(List<String> lines, int index,TecpTeclTrans tecpTeclTrans, String year) {
        Map<String,List<TecpTecl>> tecMap = new LinkedHashMap<>();
        String line = lines.get(index);
        // 卫星名称
        String startName = "";
        // 卫星号数据量存储
        int startNum = NumberUtils.toInt(line.substring(33, 36).trim());
        index ++;
        TecpTecl tecpTecl = null;
        String dateTime = "";
        for (; index < lines.size(); index ++) {
            line = lines.get(index);
            if(StringUtils.isBlank(line) || line.length() < 33
                || (!line.substring(30, 33).trim().equals("0") && !line.substring(30, 33).trim().equals("1"))){
                continue;
            }
            dateTime = TecDateFormat.format(line.substring(2, 28), 16, year);
            tecpTeclTrans.setDateTime(dateTime);
            tecpTeclTrans.setWeekSeconds(TecDateFormat.getWeekSeconds(dateTime));
            index = this.readVersion3(lines, index ++, tecpTeclTrans, tecMap, Integer.parseInt(line.substring(33, 36).trim()));
        }
        return tecMap;
    }

    private int readVersion3(List<String> lines, int index, TecpTeclTrans tecpTeclTrans,Map<String,List<TecpTecl>> tecMap,int startQty) {
        String line = "";
        TecpTecl tecpTecl = null;
        for (int i = 0; i < tecpTeclTrans.getObsTypeNum(); i ++) {
            Map<String, Double> obsTypeMap = new HashMap<>();
            line = lines.get(index ++);
            OFileTools.getObsTypeVal(line, obsTypeMap);
            tecpTecl = this.getTecpTecl(tecpTeclTrans, obsTypeMap, line.substring(0, 3).trim());
            this.appendTecpTecl(line.substring(0, 3).trim(),tecMap, tecpTecl);
        }
        return index - 1;
    }

    private Map<String,List<TecpTecl>> getVersion2(List<String> lines, int index,TecpTeclTrans tecpTeclTrans, String year) {
        Map<String,List<TecpTecl>> tecMap = new LinkedHashMap<>();
        String line = "";
        // 卫星数量
        int startQty = 0;
        // 卫星行数
        int startRow = 0;
        // 卫星名称集合
        List<String> startList = null;
        String dateTime = "";
        for (; index < lines.size(); index ++) {
            line = lines.get(index);
            startList = new ArrayList<>();
            tecpTeclTrans.setStartList(startList);
            if (StringUtils.isBlank(line) || line.length() < 29
                    || (!line.substring(26, 29).trim().equals("0") && !line.substring(26, 29).trim().equals("1"))) {
                continue;
            }
            dateTime = TecDateFormat.format(line.substring(0, 26), 15, year);
            tecpTeclTrans.setDateTime(dateTime);
            tecpTeclTrans.setWeekSeconds(TecDateFormat.getWeekSeconds(dateTime));
            startQty = NumberUtils.toInt(line.substring(29, 32).trim());
            startRow = startQty % 12 == 0 ? startQty / 12 : startQty / 12 + 1;
            // 获取卫星列表
            index = getStartList(lines, index, startRow, startList);
            index = readVersion2(lines, index, tecpTeclTrans, tecMap,startQty);
        }
        return tecMap;
    }

    /**
     * 读取TecpTecl数据
     * @param lines
     * @param index
     * @param tecpTeclTrans
     * @param tecMap
     * @return
     */
    private int readVersion2(List<String> lines, int index, TecpTeclTrans tecpTeclTrans,Map<String,List<TecpTecl>> tecMap, int startQty) {
        String line = "";
        TecpTecl tecpTecl = null;
        PathFileType pathFileType = null;
        int size = tecpTeclTrans.getObsTypeNum() % 5 == 0 ? tecpTeclTrans.getObsTypeNum() / 5 : tecpTeclTrans.getObsTypeNum() / 5 + 1;
        size = size == 0 ? 1 : size;
        for (int i = 0; i < startQty; i ++) {
            Map<String, Double> obsTypeMap = new HashMap<>();

            for (int j = 0; j < size; j++) {
                if (index >= lines.size()) {
                    return index;
                }
                line = lines.get(index);
                OFileTools.getObsTypeVal(line, tecpTeclTrans.getObsTypeList(), obsTypeMap, j * 5);
                index ++;
            }
            tecpTecl = this.getTecpTecl(tecpTeclTrans,obsTypeMap, tecpTeclTrans.getStartList().get(i));
            this.appendTecpTecl(tecpTeclTrans.getStartList().get(i),tecMap, tecpTecl);
        }
        return index - 1;
    }

    private void appendTecpTecl(String startName,Map<String,List<TecpTecl>> tecMap, TecpTecl tecpTecl){
        //当TECP和TECL为空的时候不必要算仰角和方位角
        if (tecpTecl == null) {
            return;
        }
        PathFileType pathFileType = this.getPathFileType(startName);
        if (pathFileType == null) {
            return;
        }
        if (StringUtils.isEmpty(tecMap.get(pathFileType.name()))) {
            tecMap.put(pathFileType.name(), new ArrayList<>());
        }
        tecMap.get(pathFileType.name()).add(tecpTecl);
    }

    /**
     * 获取TecpTecl对象
     *
     * @param tecpTeclTrans
     * @param obsTypeMap
     * @param startName
     * @return
     */
    private TecpTecl getTecpTecl(TecpTeclTrans tecpTeclTrans,Map<String, Double> obsTypeMap,String startName) {
        if (StringUtils.isBlank(obsTypeMap.get("L1")) || StringUtils.isBlank(obsTypeMap.get("L2"))) {
            return null;
        }

        PathFileType pathFileType = this.getPathFileType(startName);
        if (pathFileType == null) {
            return null;
        }
        // 卫星号
        int startNum = NumberUtils.toInt(startName.substring(1, 3)) - 1;
        /* if (StringUtils.isBlank(tecpTeclTrans.getNavPath()[startNum][pathFileType.getCheckIndex()]) || tecpTeclTrans.getNavPath()[startNum][pathFileType.getCheckIndex()] == -99999) {
            return null;
        }*/
        tecpTeclTrans.setL1(obsTypeMap.get("L1").toString());
        tecpTeclTrans.setL2(obsTypeMap.get("L2").toString());
        tecpTeclTrans.setStratName(startName);
        tecpTeclTrans.setStratNum(startNum + 1);
        return OFileTools.getTecpTecl(tecpTeclTrans,obsTypeMap, startNum, startName, pathFileType);
    }

    private PathFileType getPathFileType(String startName) {
        if (startName.contains("G")) {
            return PathFileType.N;
        }
        if (startName.contains("R")) {
            return PathFileType.G;
        }
        if (startName.contains("C")) {
            return PathFileType.C;
        }
        return null;
    }

    /**
     * 获取卫星号
     *
     * @return
     */
    private int getStartList(List<String> lines, int index, int startRow,List<String> startList){
        String line = "";
        int size = 0;
        for (int num = 0; num < startRow; num ++){
            line = lines.get(index ++);
            size = (line.length() - 32) / 3;
            if (size == 0) {
                continue;
            }
            for (int i = 0; i < size; i ++) {
                startList.add(line.substring(32+i*3, 32+(i+1)*3).trim());
            }
        }
        return index;
    }
}
